package com.laich.springcloud.security.conf;

import java.util.Arrays;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**
 * @author laich
 * 身份授权认证服务配置
 *  配置客户端、token存储方式等
 * @date 2019-02-11
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource; //客户端信息配置
    
    /**
     * 注入AuthenticationManager ，密码模式用到
     */
    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 认证服务器的安全配置
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
        security.tokenKeyAccess("isAuthenticated()");//isAuthenticated():排除anonymous   isFullyAuthenticated():排除anonymous以及remember-me
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    /**
     * 授权一些配置
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
       // endpoints.accessTokenConverter(jwtAccessTokenConverter());//使用jwt token方式
       // endpoints.tokenStore(jwtTokenStore());//如何存储
        //endpoints.tokenServices(defaultTokenServices());
    	
    	  TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
          tokenEnhancerChain.setTokenEnhancers(
           Arrays.asList(ustomTokenEnhancer(), jwtAccessTokenConverter()));
         
          endpoints.tokenStore(jwtTokenStore())
               .tokenEnhancer(tokenEnhancerChain)
               .authenticationManager(authenticationManager);
               //.tokenServices(defaultTokenServices());
    	
    }

    @Primary
    @Bean
    public DefaultTokenServices defaultTokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(jwtTokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }

    @Bean
    public JwtTokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    
    /**
     * 定义token 签名的方式(非对称加密算法来对 Token 进行签名,也可以使用对称加密方式)
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("laich");   
        //  Sets the JWT signing key  如果没有设置公私钥方式将是 对称密钥来签署的令牌  也可设置公私钥方式，则是非对称加密
        return jwtAccessTokenConverter;
    }
    
    @Bean
    public TokenEnhancer ustomTokenEnhancer() {
      return new CustomTokenEnhancer();
    }

}
